// RecoverStack.cpp : Defines the entry point for the DLL application.
//

#include "kevinext.h"
#include "RecoverStack.h"

BOOL	bInitialize = FALSE;

WINDBG_EXTENSION_APIS64 ExtensionApis;

IDebugClient*			pDebugClient = NULL;
IDebugControl*			pDebugControl = NULL;
IDebugAdvanced*			pDebugAdvanced = NULL;
IDebugSystemObjects*	pDebugSystemObjects = NULL;
IDebugDataSpaces*		pDebugDataSpaces = NULL;
IDebugSymbols*			pDebugSymbols = NULL;
IDebugSymbols2*			pDebugSymbols2 = NULL;

VOID ReleaseComPointers();

HRESULT CALLBACK DebugExtensionInitialize(OUT PULONG Version, OUT PULONG Flags)
{
	HRESULT hRes = E_FAIL;
	if (bInitialize == TRUE)
	{
		return S_OK;
	}

	*Version = DEBUG_EXTENSION_VERSION(1, 0);
	*Flags = 0;

	if (FAILED(hRes = DebugCreate(__uuidof(IDebugClient), (void**)&pDebugClient)))
	{
		return hRes;
	}

	if (FAILED(hRes = pDebugClient->QueryInterface(__uuidof(IDebugControl), (void**)&pDebugControl)))
	{
		ReleaseComPointers();
		return hRes;
	}

	if (FAILED(hRes = pDebugClient->QueryInterface(__uuidof(IDebugAdvanced), (void**)&pDebugAdvanced)))
	{
		ReleaseComPointers();
		return hRes;
	}

	if (FAILED(hRes = pDebugClient->QueryInterface(__uuidof(IDebugSystemObjects), (void**)&pDebugSystemObjects)))
	{
		ReleaseComPointers();
		return hRes;
	}

	if (FAILED(hRes = pDebugClient->QueryInterface(__uuidof(IDebugDataSpaces), (void**)&pDebugDataSpaces)))
	{
		ReleaseComPointers();
		return hRes;
	}

	if (FAILED(hRes = pDebugClient->QueryInterface(__uuidof(IDebugSymbols), (void**)&pDebugSymbols)))
	{
		ReleaseComPointers();
		return hRes;
	}

	if (FAILED(hRes = pDebugClient->QueryInterface(__uuidof(IDebugSymbols2), (void**)&pDebugSymbols2)))
	{
		ReleaseComPointers();
		return hRes;
	}

	ExtensionApis.nSize = sizeof(ExtensionApis);
	hRes = pDebugControl->GetWindbgExtensionApis64(&ExtensionApis);

	bInitialize = TRUE;
	hRes = S_OK;
	return hRes;
}

void CALLBACK DebugExtensionUninitialize()
{
	ReleaseComPointers();
}

HRESULT CALLBACK help(PDEBUG_CLIENT pClient, PCSTR szArgs)
{
	dprintf("this is help");
	return S_OK;
}

HRESULT CALLBACK RecoverStack(PDEBUG_CLIENT pClient, PCSTR szArgs)
{
	CRecoverStack* oCmd = new CRecoverStack;
	oCmd->RecoverStackInternal();
	delete oCmd;
	return S_OK;
}

VOID ReleaseComPointers()
{
	if (pDebugClient) pDebugClient->Release();
	if (pDebugControl) pDebugControl->Release();
	if (pDebugAdvanced) pDebugAdvanced->Release();
	if (pDebugSystemObjects) pDebugSystemObjects->Release();
	if (pDebugDataSpaces) pDebugDataSpaces->Release();
	if (pDebugSymbols) pDebugSymbols->Release();
	if (pDebugSymbols2) pDebugSymbols2->Release();
}